/**
 * 
 */
package metier;

import java.io.IOException;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Map.Entry;

import org.annolab.tt4j.TokenHandler;
import org.annolab.tt4j.TreeTaggerException;
import org.annolab.tt4j.TreeTaggerWrapper;
import org.apache.commons.lang.StringUtils;

import controller.MatriceDocMot;

/**
 * @author xavier
 * 
 */
public class FiltreMetier {
	private Boolean accent;
	private Boolean normalisation;
	private Boolean lematisation;
	private Boolean miniscule;
	private String adjPossessif;
	private String frequent;
	private String rare;
	private Integer longueur;
	private final Integer LONGUEUR_MINI_BASE = 3;

	public FiltreMetier() {
		this.accent = Boolean.FALSE;
		this.normalisation = Boolean.FALSE;
		this.miniscule = Boolean.FALSE;
		this.lematisation = Boolean.TRUE;
		this.adjPossessif = "";
		this.frequent = "";
		this.rare = "";
		this.longueur = LONGUEUR_MINI_BASE;
	}

	public FiltreMetier(Boolean accentUn, Boolean normalisationUn,
			Boolean lematisationUn, Boolean minisculeUn, String adjPossessifUn,
			String frequentUn, String rareUn, Integer longueurUn) {
		this.accent = accentUn;
		this.normalisation = normalisationUn;
		this.miniscule = minisculeUn;
		this.lematisation = lematisationUn;
		this.adjPossessif = adjPossessifUn;
		this.frequent = frequentUn;
		this.rare = rareUn;
		this.longueur = longueurUn;
	}

	/**
	 * Enleve les mots qui ont une taille plus petite que tailleMini
	 * 
	 * @param texte
	 *            Le texte à traiter
	 * @param tailleMini
	 *            La taille minimum des mots
	 * @return Le texte traité
	 */
	public List<String> motTailleN(List<String> texte, Integer tailleMini) {
		List<String> res = new ArrayList<String>();
		for (String mot : texte) {
			mot = mot.trim();
			if (mot.length() > tailleMini)
				res.add(mot);
		}
		return res;
	}

	/**
	 * Supprime tous les caractères non alphabetiques d'un texte. Les accents
	 * doivent être supprimés avant.
	 * 
	 * @param texte
	 *            La list de texte à traiter
	 * @return Le texte traité
	 */
	public List<String> normalisation(List<String> texte) {
		// Créer la liste de retour
		List<String> retour = new ArrayList<String>();
		// Test tous les mots et supprime tous les caractères non alphabétiques
		// et non espace
		for (String mot : texte) {
			mot = mot.replaceAll("[^A-Za-z]", " ");
			if (StringUtils.isNotBlank(mot)) {
				retour.add(mot);
			}

		}
		return retour;
	}

	/**
	 * Renvoi le texte sans les adjectifs possessifs contenus dans le fichier
	 * adjectifsPossessifs.txt
	 * 
	 * @param texte
	 *            Le texte à traiter
	 * @return Le texte traité
	 */
	public List<String> adjectifPossessif(List<String> texte) {
		if (!this.adjPossessif.equals("")) {
			// Chargement des adjectifs possessifs en bloc
			String adjPossessifs = ChargerFichier
					.lireFichier("filtres/adjectifsPossessifs/"
							+ this.adjPossessif);
			// Séparation du bloc pour obtenir une liste d'ajectifs possessifs
			List<String> listeAdjPossessifs = new ArrayList<String>(
					Arrays.asList(adjPossessifs.split(";")));
			// Création de la liste de retour
			List<String> res = new ArrayList<String>();
			if (texte != null && listeAdjPossessifs != null) {
				// Parcours du texte et ajout du mot dans res s'il n'appartient
				// pas
				// à la liste des adjectifs
				for (String tmp : texte) {
					if (!listeAdjPossessifs.contains(tmp)) {
						res.add(tmp);
					}
				}
			}
			return res;
		}
		return texte;
	}

	/**
	 * Renvoie le texte en minuscule.
	 * 
	 * @param texte
	 *            Le texte à traiter
	 * @return Le texte traité
	 */
	public List<String> minuscule(List<String> texte) {
		List<String> res = new ArrayList<>();
		for (String mot : texte) {
			res.add(mot.toLowerCase());
		}
		return res;
	}

	/**
	 * Renvoit le texte en enlevant les accents
	 * 
	 * @param texte
	 *            Le texte à traiter
	 * @return Le texte traité
	 */
	public List<String> accent(List<String> texte) {
		List<String> res = new ArrayList<>();
		for (String mot : texte) {
			String motSansAccent = Normalizer.normalize(mot,
					Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "");
			if (StringUtils.isNotBlank(motSansAccent)) {
				res.add(motSansAccent);
			}
		}
		return res;
	}

	// Renvoit le texte lemmatisé
	public List<String> lemmatisation(List<String> texte) {
		for (String travail : texte) {
			travail.trim();
		}
		final List<String> res = new ArrayList<String>();

		TreeTaggerWrapper<String> tt = new TreeTaggerWrapper<String>();
		System.setProperty("treetagger.home", "treetagger");
		try {
			tt.setModel("french-par-linux-3.2-utf8.bin");
			tt.setHandler(new TokenHandler<String>() {
				public void token(String token, String pos, String lemma) {
					res.add(lemma);

				}
			});
			tt.process(texte);
		} catch (TreeTaggerException | IOException e) {
			e.printStackTrace();
		}
		final List<String> retour = new ArrayList<String>();
		for (String travail : res) {
			retour.add(travail.replaceAll("_", " "));
		}
		return retour;
	}

	public List<String> transformationEnListPointVirgule(String contenuFichier) {
		String[] stringApresSplit = contenuFichier.trim().split(";");
		List<String> liste = new ArrayList<String>();
		for (int index = 0; index < stringApresSplit.length; index++) {
			liste.add(stringApresSplit[index]);
		}
		return liste;

	}

	/**
	 * Transforme une String en List de String. Le string est découpé avec les
	 * espaces.
	 * 
	 * @param contenuFichier
	 *            Le String à découper
	 * @return Le string découpé.
	 */
	public List<String> transformationEnList(String contenuFichier) {
		String[] stringApresSplit = contenuFichier.trim().split(" ");
		List<String> liste = new ArrayList<String>();
		for (int index = 0; index < stringApresSplit.length; index++) {
			liste.add(stringApresSplit[index]);
		}
		return liste;
	}

	/**
	 * @return the accent
	 */
	public Boolean getAccent() {
		return accent;
	}

	/**
	 * @param accent
	 *            the accent to set
	 */
	public void setAccent(Boolean accent) {
		this.accent = accent;
	}

	/**
	 * @return the normalisation
	 */
	public Boolean getNormalisation() {
		return normalisation;
	}

	/**
	 * @param normalisation
	 *            the normalisation to set
	 */
	public void setNormalisation(Boolean normalisation) {
		this.normalisation = normalisation;
	}

	/**
	 * @return the lematisation
	 */
	public Boolean getLematisation() {
		return lematisation;
	}

	/**
	 * @param lematisation
	 *            the lematisation to set
	 */
	public void setLematisation(Boolean lematisation) {
		this.lematisation = lematisation;
	}

	/**
	 * @return the miniscule
	 */
	public Boolean getMiniscule() {
		return miniscule;
	}

	/**
	 * @param miniscule
	 *            the miniscule to set
	 */
	public void setMiniscule(Boolean miniscule) {
		this.miniscule = miniscule;
	}

	/**
	 * @return the adjPossessif
	 */
	public String getAdjPossessif() {
		return adjPossessif;
	}

	/**
	 * @param adjPossessif
	 *            the adjPossessif to set
	 */
	public void setAdjPossessif(String adjPossessif) {
		this.adjPossessif = adjPossessif;
	}

	/**
	 * @return the frequent
	 */
	public String getFrequent() {
		return frequent;
	}

	/**
	 * @param frequent
	 *            the frequent to set
	 */
	public void setFrequent(String frequent) {
		this.frequent = frequent;
	}

	/**
	 * @return the rare
	 */
	public String getRare() {
		return rare;
	}

	/**
	 * @param rare
	 *            the rare to set
	 */
	public void setRare(String rare) {
		this.rare = rare;
	}

	/**
	 * @return the longueur
	 */
	public Integer getLongueur() {
		return longueur;
	}

	/**
	 * @param longueur
	 *            the longueur to set
	 */
	public void setLongueur(Integer longueur) {
		this.longueur = longueur;
	}
}
